home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Graphics Programming (2nd Edition) / Visual Basic Graphics Programming 2nd Edition.iso / OldSrc / CH10 / SRC / BSPLINE.CLS < prev    next >
Text File  |  1996-05-04  |  13KB  |  454 lines

  1. VERSION 1.0 CLASS
  2. BEGIN
  3.   MultiUse = -1  'True
  4. END
  5. Attribute VB_Name = "ObjBSpline"
  6. Attribute VB_Creatable = False
  7. Attribute VB_Exposed = False
  8. Option Explicit
  9.  
  10. Private DegreeU As Integer  ' Degree in U direction.
  11. Private DegreeV As Integer  ' Degree in V direction.
  12. Private MaxU As Integer     ' Dimensions of control grid.
  13. Private MaxV As Integer
  14. Private Points() As Point3D ' Control points.
  15.  
  16. ' grid holds a refined grid to display the surface.
  17. Private grid As ObjPicture
  18.  
  19. ' u and v increment parameters.
  20. Private GapU As Single
  21. Private GapV As Single
  22. Private Du As Single
  23. Private Dv As Single
  24.  
  25. ' Display flags.
  26. Private ShowControls As Boolean ' Draw control points?
  27. Private ShowGrid As Boolean     ' Draw control grid?
  28.  
  29. Function Factorial(ByVal n As Single) As Single
  30. Dim i As Integer
  31. Dim tot As Single
  32.  
  33.     tot = 1
  34.     For i = 2 To n
  35.         tot = tot * i
  36.     Next i
  37.     Factorial = tot
  38. End Function
  39.  
  40. ' ************************************************
  41. ' Create the refined grid to display the surface.
  42. ' ************************************************
  43. Public Sub InitializeGrid(degu As Integer, degv As Integer, gap_u As Single, gap_v As Single, d_u As Single, d_v As Single)
  44. Dim u As Single
  45. Dim v As Single
  46. Dim stopu As Single
  47. Dim stopv As Single
  48. Dim x As Single
  49. Dim y As Single
  50. Dim z As Single
  51. Dim x1 As Single
  52. Dim y1 As Single
  53. Dim z1 As Single
  54. Dim pline As ObjPolyline
  55.  
  56.     DegreeU = degu
  57.     DegreeV = degv
  58.     GapU = gap_u
  59.     GapV = gap_v
  60.     Du = d_u
  61.     Dv = d_v
  62.     
  63.     Set grid = New ObjPicture
  64.     
  65.     ' Create curves with constant u.
  66.     stopu = MaxU - DegreeU + 2 + GapU / 10
  67.     stopv = MaxV - DegreeV + 2 + Dv / 10
  68.     For u = 0 To stopu Step GapU
  69.         Set pline = New ObjPolyline
  70.         grid.objects.Add pline
  71.         
  72.         SurfaceValue u, 0, x1, y1, z1
  73.         
  74.         For v = Dv To stopv Step Dv
  75.             SurfaceValue u, v, x, y, z
  76.             pline.AddSegment x1, y1, z1, x, y, z
  77.             x1 = x
  78.             y1 = y
  79.             z1 = z
  80.         Next v
  81.     Next u
  82.  
  83.     ' Create curves with constant v.
  84.     stopv = MaxV - DegreeV + 2 + GapV / 10
  85.     stopu = MaxU - DegreeU + 2 + Du / 10
  86.     For v = 0 To stopv Step GapV
  87.         Set pline = New ObjPolyline
  88.         grid.objects.Add pline
  89.         
  90.         SurfaceValue 0, v, x1, y1, z1
  91.         For u = Du To stopu Step Du
  92.             SurfaceValue u, v, x, y, z
  93.             pline.AddSegment x1, y1, z1, x, y, z
  94.             x1 = x
  95.             y1 = y
  96.             z1 = z
  97.         Next u
  98.     Next v
  99. End Sub
  100. ' ************************************************
  101. ' Apply a transformation matrix which may not
  102. ' contain 0, 0, 0, 1 in the last column to the
  103. ' object.
  104. ' ************************************************
  105. Public Sub ApplyFull(M() As Single)
  106. Dim i As Integer
  107. Dim j As Integer
  108.     
  109.     ' Apply the matrix to the grid if it exists.
  110.     If Not grid Is Nothing Then grid.ApplyFull M
  111.  
  112.     ' Apply the matrix to the control points.
  113.     For i = 0 To MaxU
  114.         For j = 0 To MaxV
  115.             m3ApplyFull Points(i, j).coord, M, Points(i, j).trans
  116.         Next j
  117.     Next i
  118. End Sub
  119. ' ************************************************
  120. ' Apply a nonlinear transformation.
  121. ' ************************************************
  122. Public Sub Distort(D As Object)
  123. Dim i As Integer
  124. Dim j As Integer
  125.     
  126.     ' Distort the grid if it exists.
  127.     If Not grid Is Nothing Then grid.Distort D
  128.  
  129.     ' Distort the sparse data.
  130.     For i = 0 To MaxU
  131.         For j = 0 To MaxV
  132.             D.Distort Points(i, j).coord(1), Points(i, j).coord(2), Points(i, j).coord(3)
  133.         Next j
  134.     Next i
  135. End Sub
  136. ' ************************************************
  137. ' Draw the transformed object on a Form, Printer,
  138. ' or PictureBox.
  139. ' ************************************************
  140. Public Sub Draw(canvas As Object, Optional r As Variant)
  141. Dim i As Integer
  142. Dim j As Integer
  143.     
  144.     ' Draw the grid if it exists.
  145.     If Not grid Is Nothing Then grid.Draw canvas, r
  146.  
  147.     ' Draw the control points if desired.
  148.     If ShowControls Then
  149.         On Error Resume Next
  150.         For i = 0 To MaxU
  151.             For j = 0 To MaxV
  152.                 canvas.Line (Points(i, j).trans(1) - 2, Points(i, j).trans(2) - 2)-Step(4, 4), , BF
  153.             Next j
  154.         Next i
  155.     End If
  156.  
  157.     ' Draw the control grid if desired.
  158.     If ShowGrid Then
  159.         On Error Resume Next
  160.         For i = 0 To MaxU
  161.             canvas.CurrentX = Points(i, 0).trans(1)
  162.             canvas.CurrentY = Points(i, 0).trans(2)
  163.             For j = 1 To MaxV
  164.                 canvas.Line -(Points(i, j).trans(1), Points(i, j).trans(2))
  165.             Next j
  166.         Next i
  167.         For j = 0 To MaxV
  168.             canvas.CurrentX = Points(0, j).trans(1)
  169.             canvas.CurrentY = Points(0, j).trans(2)
  170.             For i = 1 To MaxU
  171.                 canvas.Line -(Points(i, j).trans(1), Points(i, j).trans(2))
  172.             Next i
  173.         Next j
  174.     End If
  175. End Sub
  176.  
  177. ' ************************************************
  178. ' Read a B-Spline surface from a file using Input.
  179. ' Assume the "BSPLINE" label has already been
  180. ' read.
  181. ' ************************************************
  182. Public Sub FileInput(filenum As Integer)
  183. Dim i As Integer
  184. Dim j As Integer
  185.  
  186.     ' Get the basic information.
  187.     Input #filenum, _
  188.         DegreeU, DegreeV, MaxU, MaxV, GapU, GapV, _
  189.         Du, Dv
  190.  
  191.     ' Allocate the Data array.
  192.     SetBounds MaxU + 1, MaxV + 1
  193.     
  194.     ' Read the control points.
  195.     For i = 0 To MaxU
  196.         For j = 0 To MaxV
  197.             Input #filenum, _
  198.                 Points(i, j).coord(1), _
  199.                 Points(i, j).coord(2), _
  200.                 Points(i, j).coord(3)
  201.             Points(i, j).coord(4) = 1
  202.         Next j
  203.     Next i
  204.     
  205.     ' Initialize the grid data.
  206.     If Du = 0 Then
  207.         Set grid = Nothing
  208.     Else
  209.         InitializeGrid DegreeU, DegreeV, _
  210.             GapU, GapV, Du, Dv
  211.     End If
  212. End Sub
  213.  
  214.  
  215.  
  216.  
  217. ' ************************************************
  218. ' Write a B-Spline surface to a file using Write.
  219. ' Begin with "BSPLINE" to identify this object.
  220. ' ************************************************
  221. Public Sub FileWrite(filenum As Integer)
  222. Dim i As Integer
  223. Dim j As Integer
  224.  
  225.     ' Write basic information.
  226.     Write #filenum, "BSPLINE", _
  227.         DegreeU, DegreeV, MaxU, MaxV, GapU, GapV, _
  228.         Du, Dv
  229.         
  230.     ' Write the data.
  231.     For i = 0 To MaxU
  232.         For j = 0 To MaxV
  233.             Write #filenum, _
  234.                 Points(i, j).coord(1), _
  235.                 Points(i, j).coord(2), _
  236.                 Points(i, j).coord(3)
  237.         Next j
  238.     Next i
  239. End Sub
  240. ' ************************************************
  241. ' Write the B-Spline curve's grid object to a file
  242. ' using Write. The data can later be loaded into
  243. ' an ObjPicture object but not an ObjBSpline
  244. ' object.
  245. ' ************************************************
  246. Public Sub FileWriteGrid(filenum As Integer)
  247.     If Not grid Is Nothing Then grid.FileWrite filenum
  248. End Sub
  249.  
  250. ' ***********************************************
  251. ' Fix the data coordinates at their transformed
  252. ' values.
  253. ' ***********************************************
  254. Public Sub FixPoints()
  255. Dim i As Integer
  256. Dim j As Integer
  257. Dim k As Integer
  258.  
  259.     ' Fix the grid points if the grid exists.
  260.     If Not grid Is Nothing Then grid.FixPoints
  261.  
  262.     ' Fix the controls points.
  263.     For i = 0 To MaxU
  264.         For j = 0 To MaxV
  265.             For k = 1 To 3
  266.                 Points(i, j).coord(k) = _
  267.                     Points(i, j).trans(k)
  268.             Next k
  269.         Next j
  270.     Next i
  271. End Sub
  272.  
  273. ' ************************************************
  274. ' Return the knot value.
  275. ' ************************************************
  276. Private Function Knot(i As Integer, max As Integer, degree As Integer) As Integer
  277.     If i < degree Then
  278.         Knot = 0
  279.     ElseIf i <= max Then
  280.         Knot = i - degree + 1
  281.     Else
  282.         Knot = max - degree + 2
  283.     End If
  284. End Function
  285.  
  286.  
  287. ' ************************************************
  288. ' Return the value of the blending function Ni,k.
  289. ' ************************************************
  290. Private Function NValue(i As Integer, max As Integer, degree As Integer, max_degree As Integer, u As Single) As Single
  291. Dim denom As Single
  292. Dim v1 As Single
  293. Dim v2 As Single
  294.  
  295.     If degree = 1 Then
  296.         If Knot(i, max, max_degree) <= u And _
  297.          u < Knot(i + 1, max, max_degree) Then
  298.             NValue = 1
  299.         Else
  300.             NValue = 0
  301.         End If
  302.         
  303.         ' Recall that:
  304.         '   Ni,1(u) = 0     if ti <= u < ti+1
  305.         '             1     otherwise
  306.         ' The following test handles u = tmax.
  307.         If i = max And _
  308.             Knot(i, max, max_degree) <= u And _
  309.             u <= Knot(i + 1, max, max_degree) + 0.001 Then
  310.                 NValue = 1
  311.         End If
  312.         Exit Function
  313.     End If
  314.     
  315.     denom = Knot(i + degree - 1, max, max_degree) - _
  316.         Knot(i, max, max_degree)
  317.     If denom = 0 Then
  318.         v1 = 0
  319.     Else
  320.         v1 = (u - Knot(i, max, max_degree)) * _
  321.             NValue(i, max, degree - 1, max_degree, u) / _
  322.             denom
  323.     End If
  324.  
  325.     denom = Knot(i + degree, max, max_degree) - _
  326.         Knot(i + 1, max, max_degree)
  327.     If denom = 0 Then
  328.         v2 = 0
  329.     Else
  330.         v2 = (Knot(i + degree, max, max_degree) - u) * _
  331.             NValue(i + 1, max, degree - 1, max_degree, u) / _
  332.             denom
  333.     End If
  334.  
  335.     NValue = v1 + v2
  336. End Function
  337.  
  338. ' ***********************************************
  339. ' Return a string indicating the object type.
  340. ' ***********************************************
  341. Property Get ObjectType() As String
  342.     ObjectType = "BSPLINE"
  343. End Property
  344. ' ************************************************
  345. ' Let the user know if we are drawing the control
  346. ' grid.
  347. ' ************************************************
  348. Property Get DrawGrid() As Boolean
  349.     DrawGrid = ShowGrid
  350. End Property
  351.  
  352. ' ************************************************
  353. ' Let the user know if we are drawing the control
  354. ' points.
  355. ' ************************************************
  356. Property Get DrawControls() As Boolean
  357.     DrawControls = ShowControls
  358. End Property
  359.  
  360.  
  361. ' ************************************************
  362. ' Let the user decide whether we should draw the
  363. ' control grid.
  364. ' ************************************************
  365. Property Let DrawGrid(value As Boolean)
  366.     ShowGrid = value
  367. End Property
  368. ' ************************************************
  369. ' Let the user decide whether we should draw the
  370. ' control points.
  371. ' ************************************************
  372. Property Let DrawControls(value As Boolean)
  373.     ShowControls = value
  374. End Property
  375.  
  376.  
  377.  
  378.  
  379. ' ************************************************
  380. ' Apply a transformation matrix to the object.
  381. ' ************************************************
  382. Public Sub Apply(M() As Single)
  383. Dim i As Integer
  384. Dim j As Integer
  385.     
  386.     ' Apply the matrix to the grid if it exists.
  387.     If Not grid Is Nothing Then grid.Apply M
  388.  
  389.     ' Apply the matrix to the control points.
  390.     For i = 0 To MaxU
  391.         For j = 0 To MaxV
  392.             m3Apply Points(i, j).coord, M, Points(i, j).trans
  393.         Next j
  394.     Next i
  395. End Sub
  396.  
  397.  
  398.  
  399.  
  400.  
  401. ' ************************************************
  402. ' Set MaxU and MaxV ans allocate room for the
  403. ' control points.
  404. ' ************************************************
  405. Public Sub SetBounds(NumX As Integer, NumZ As Integer)
  406.     MaxU = NumX - 1
  407.     MaxV = NumZ - 1
  408.     ReDim Points(0 To NumX, 0 To NumZ)
  409. End Sub
  410.  
  411. ' ************************************************
  412. ' Set the value for a control point.
  413. ' ************************************************
  414. Public Sub SetControlPoint(i As Integer, j As Integer, x As Single, y As Single, z As Single)
  415.     Points(i - 1, j - 1).coord(1) = x
  416.     Points(i - 1, j - 1).coord(2) = y
  417.     Points(i - 1, j - 1).coord(3) = z
  418.     Points(i - 1, j - 1).coord(4) = 1
  419. End Sub
  420. ' ************************************************
  421. ' Return the value of the B-Spline surface at this
  422. ' position.
  423. ' ************************************************
  424. Private Sub SurfaceValue(u As Single, v As Single, x As Single, y As Single, z As Single)
  425. Dim p As Integer
  426. Dim i As Integer
  427. Dim j As Integer
  428. Dim pt As Point3D
  429. Dim Ni As Single
  430. Dim Nj As Single
  431.  
  432.     For i = 0 To MaxU
  433.         ' Compute Ni.
  434.         Ni = NValue(i, MaxU, DegreeU, DegreeU, u)
  435.  
  436.         For j = 0 To MaxV
  437.             ' Compute Nj.
  438.             Nj = NValue(j, MaxV, DegreeV, DegreeV, v)
  439.             
  440.             ' Add to the coordinates.
  441.             For p = 1 To 3
  442.                 pt.coord(p) = pt.coord(p) + _
  443.                     Points(i, j).coord(p) * _
  444.                     Ni * Nj
  445.             Next p
  446.         Next j
  447.     Next i
  448.     
  449.     ' Prepare the output.
  450.     x = pt.coord(1)
  451.     y = pt.coord(2)
  452.     z = pt.coord(3)
  453. End Sub
  454.